﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ShopSpace.Core
{
	/// <summary>
	/// Represents an task in a project
	/// </summary>
	public class WorkItem : Entity
	{
		#region private fields

		private Person assignedTo;
		private Milestone milestone;

		#endregion

		#region Constructors

		protected WorkItem()
		{
			this.LogEntries = new List<LogEntry>();
			this.Milestone = Milestone.NOT_ASSIGNED;
		}

		public WorkItem(Project project, Person reportedBy, string summary)
			 : this()
		{
			this.Project = project;
			this.ReportedBy = reportedBy;
			this.Summary = summary;
			this.AddLogEntry(LogEntryType.Created, reportedBy);
		}

		#endregion

		#region Methods

		protected void AddMilestoneChangedLogEntry(Milestone oldMilestone, Milestone newMilestone, Person changedBy)
		{
			LogEntry logEntry = this.AddLogEntry(LogEntryType.MilestoneChanged, changedBy);
			logEntry.Detail = string.Format("was {0}, now {1}", oldMilestone.Name, newMilestone.Name);
		}

		public virtual LogEntry AddLogEntry(LogEntryType type, Person who)
		{
			LogEntry logEntry = new LogEntry(this, who, type);
			this.LogEntries.Add(logEntry);
			return logEntry;
		}

		public virtual void ChangeMilestone(Milestone newMilestone, Person changedBy)
		{
			if (this.Milestone != Milestone.NOT_ASSIGNED && newMilestone != Milestone.NOT_ASSIGNED)
			{
				if (newMilestone != this.Milestone)
				{
					this.MilestoneWasChanged = true;
					this.AddMilestoneChangedLogEntry(this.Milestone, newMilestone, changedBy);
				}
			}
			else if (this.Milestone != Milestone.NOT_ASSIGNED && newMilestone == Milestone.NOT_ASSIGNED)
			{
				this.MilestoneWasChanged = true;
				this.AddMilestoneChangedLogEntry(this.Milestone, newMilestone, changedBy);
			}
			else if (this.Milestone == Milestone.NOT_ASSIGNED && newMilestone != Milestone.NOT_ASSIGNED)
			{
				this.MilestoneWasChanged = true;
				this.AddMilestoneChangedLogEntry(this.Milestone, newMilestone, changedBy);
			}
			this.Milestone = newMilestone;
		}

		public virtual void ChangePriority(Priority newPriority, Person changedBy)
		{
			if (newPriority != this.Priority)
			{
				this.PriorityWasChanged = true;
				LogEntry logEntry = this.AddLogEntry(LogEntryType.PriorityChanged, changedBy);
				logEntry.Detail = string.Format("was {0}, now {1}", this.Priority.ToString(), newPriority.ToString());
			}
			this.Priority = newPriority;
		}

		public virtual void ChangeStatus(WorkItemStatus newStatus, Person changedBy)
		{
			if (this.Status != null && newStatus != this.Status)
			{
				this.StatusWasChanged = true;
				LogEntry logEntry = this.AddLogEntry(LogEntryType.StatusChanged, changedBy);
				logEntry.Detail = string.Format("was {0}, now {1}", this.Status.Description, newStatus.Description);
			}
			this.Status = newStatus;
		}

		#endregion

		#region Properties

		/// <summary>
		/// Gets or sets the LogEntries
		/// of the WorkItem
		/// </summary>
		protected virtual IList<LogEntry> LogEntries
		{
			get;
			set;
		}

		/// <summary>
		/// Gets or sets the Summary (brief description)
		/// </summary>
		public virtual string Summary
		{
			get;
			set;
		}

		/// <summary>
		/// Gets the Project that the WorkItem
		/// is a part of
		/// </summary>
		public virtual Project Project
		{
			get;
			protected set;
		}

		/// <summary>
		/// Gets or set the Description
		/// of the WorkItem
		/// </summary>
		public virtual string Description
		{
			get;
			set;
		}

		/// <summary>
		/// Gets the Person who reported
		/// the WorkItem
		/// </summary>
		public virtual Person ReportedBy
		{
			get;
			protected set;
		}

		/// <summary>
		/// Gets or sets the Person
		/// assigned to work on the
		/// WorkItem
		/// </summary>
		public virtual Person AssignedTo
		{
			get
			{
				if (this.assignedTo ==null)
				{
					return Person.NOT_ASSIGNED;
				}
				return this.assignedTo;
			}
			set
			{
				if (value == Person.NOT_ASSIGNED)
				{
					this.assignedTo = null;
				}
				else
				{
					this.assignedTo = value;
				}
			}
		}

		/// <summary>
		/// Gets or sets the WorkItemCategory
		/// </summary>
		public virtual WorkItemCategory Category
		{
			get;
			set;
		}

		/// <summary>
		/// Gets the WorkItemStatus
		/// </summary>
		public virtual WorkItemStatus Status
		{
			get;
			protected set;
		}

		/// <summary>
		/// Inidcates if this instance's Status has been changed (Transient)
		/// </summary>
		public virtual bool StatusWasChanged
		{
			get;
			protected set;
		}
		
		/// <summary>
		/// Gets the Priority
		/// </summary>
		public virtual Priority Priority
		{
			get;
			protected set;
		}

		/// <summary>
		/// Inidcates if this instance's Priority has been changed (Transient)
		/// </summary>
		public virtual bool PriorityWasChanged
		{
			get;
			protected set;
		}

	
		/// <summary>
		/// Gets or sets a target Milestone
		/// </summary>
		public virtual Milestone Milestone
		{
			get
			{
				if (this.milestone == null)
				{
					return Milestone.NOT_ASSIGNED;
				}
				return this.milestone;
			}
			set
			{
				if (value == Milestone.NOT_ASSIGNED)
				{
					this.milestone = null;
				}
				else
				{
					this.milestone = value;
				}
			}
		}

		/// <summary>
		/// Inidcates if this instance's Milestone has been changed (Transient)
		/// </summary>
		public virtual bool MilestoneWasChanged
		{
			get;
			protected set;
		}

		#endregion
	}
}
